﻿using System.Collections.Generic;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using WalkingTec.Mvvm.Core;
using WalkingTec.Mvvm.Core.Support.FileHandlers;
using WalkingTec.Mvvm.Mvc;
using System;
using System.Text.Json.Serialization;
using HengTong.DataAccess;
using HengTong.Kingdee.Eas;
using HengTong.Model.Services;
using HengTong.Services;
using HengTong.Tasks;
using Microsoft.EntityFrameworkCore;
using Serilog;
using TiaoTaoHelper.Wtm.Extension;
using TiaoTaoHelper.Wtm.Interfaces;
using TiaoTaoHelper.Wtm.Services;

namespace HengTong
{
    public class Startup
    {
        public IConfiguration ConfigRoot { get; }

        public Startup(IWebHostEnvironment env, IConfiguration config)
        {
            AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
            ConfigRoot = config;
        }
        
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddXenWorkflow(ConfigRoot);
            services.AddDistributedMemoryCache();
            services.AddWtmSession(3600, ConfigRoot);
            services.AddWtmCrossDomain(ConfigRoot);
            services.AddWtmAuthentication(ConfigRoot);
            services.AddWtmHttpClient(ConfigRoot);
            services.AddXenSwagger();
            services.AddWtmMultiLanguages(ConfigRoot);
            services.AddMvc(options =>
            {
                options.UseWtmMvcOptions();
            })
            .AddJsonOptions(options => {
                options.UseWtmJsonOptions();
                options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString;
            })
            .ConfigureApiBehaviorOptions(options =>
            {
                options.UseWtmApiOptions();
            })
            .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
            .AddWtmDataAnnotationsLocalization(typeof(Program));

            services.AddWtmContext(ConfigRoot, (options) => {
                options.DataPrivileges = DataPrivilegeSettings();
                options.CsSelector = CSSelector;
                options.FileSubDirSelector = SubDirSelector;
                options.ReloadUserFunc = ReloadUser;
            });
            services.Configure<RazorViewEngineOptions>(options =>
            {
                options.ViewLocationFormats.Add("/Views/Themes/{0}.cshtml");
                options.ViewLocationFormats.Add("/Views/Themes/{0}/{1}.cshtml");
            });
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "wwwroot";
            });
            services.AddLogging(configure =>
            {
                configure.AddSerilog(dispose: true);
            });
            services.AddCodeGen();
            services.AddScoped<AwsTaskService>();
            services.AddMemoryCache(); // 如果还没添加内存缓存
            services.AddScoped<ISmsAuthService, SmsAuthService>();
            services.AddScoped<IWechatAuthService, WechatAuthService>();
            services.AddScoped<CodeGeneratorService>();
            // 注册HttpClient和身份证识别服务
            services.AddHttpClient<IIdentityCardRecognitionService, IdentityCardRecognitionService>();
            services.AddScoped<IIdentityCardRecognitionService, IdentityCardRecognitionService>();
            services.AddScoped<IWorkflowNotification, WorkflowNotificationService>();
            // 注册证件照服务
            services.AddScoped<IPortraitPhotoService, PortraitPhotoService>();
            // 注册数据同步服务
            services.AddEasService(ConfigRoot);
            services.AddScoped<DataSyncService>();
#if !DEBUG
            // 注册任务调度
            services.AddHostedService<QuartzHostService>();
            services.AddScoped<UpdatePersonAgeTask>();
#endif
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IOptionsMonitor<Configs> configs, IHostEnvironment env, WTMContext wtm)
        {
            if (wtm.DC is DataContext dc)
            {
                dc.Database.Migrate();
            }
            app.UseExceptionHandler(configs.CurrentValue.ErrorHandler);
            DefaultFilesOptions defaultFilesOptions = new DefaultFilesOptions();
            defaultFilesOptions.DefaultFileNames.Clear();
            defaultFilesOptions.DefaultFileNames.Add("index.html");
            app.UseDefaultFiles(defaultFilesOptions);
            app.UseStaticFiles();
            app.UseWtmStaticFiles();
            app.UseSpaStaticFiles();
            app.UseXenSwagger();
            app.UseRouting();
            app.UseWtmMultiLanguages();
            app.UseWtmCrossDomain();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseSession();
            app.UseWtm();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                   name: "areaRoute",
                   pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
                endpoints.MapFallbackToFile(env.IsDevelopment() ? "index_dev.html" : "");
            });
            app.UseWtmContext();
        }

        /// <summary>
        /// Wtm will call this function to dynamiclly set connection string
        /// 框架会调用这个函数来动态设定每次访问需要链接的数据库
        /// </summary>
        /// <param name="context">ActionContext</param>
        /// <returns>Connection string key name</returns>
        public string CSSelector(ActionExecutingContext context)
        {
            //To override the default logic of choosing connection string,
            //change this function to return different connection string key
            //根据context返回不同的连接字符串的名称
            return null;
        }

        /// <summary>
        /// Set data privileges that system supports
        /// 设置系统支持的数据权限
        /// </summary>
        /// <returns>data privileges list</returns>
        public List<IDataPrivilege> DataPrivilegeSettings()
        {
            List<IDataPrivilege> pris = new List<IDataPrivilege>();
            //Add data privilege to specific type
            //指定哪些模型需要数据权限
            
            return pris;
        }

        /// <summary>
        /// Set sub directory of uploaded files
        /// 动态设置上传文件的子目录
        /// </summary>
        /// <param name="fh">IWtmFileHandler</param>
        /// <returns>subdir name</returns>
        public string SubDirSelector(IWtmFileHandler fh)
        {
            return null;
        }

        /// <summary>
        /// Custom Reload user process when cache is not available
        /// 设置自定义的方法重新读取用户信息，这个方法会在用户缓存失效的时候调用
        /// </summary>
        /// <param name="context"></param>
        /// <param name="account"></param>
        /// <returns></returns>
        public LoginUserInfo ReloadUser(WTMContext context, string account)
        {
            return null;
        }
    }
}

